/**
 * 
 */
package com;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;

import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;

import com.SDFSProtocol;


/**
 * @author kévin+moaad
 *
 */
public class SDFSMultiServerThread extends Thread {

	private SSLSocket clientSocket = null;
	private boolean certificatOK = true;
	String clientID = "";

	public SDFSMultiServerThread(SSLSocket socket) {
		super("SDFSMultiServerThread");
		this.clientSocket = socket;
		SSLSession sslSession = clientSocket.getSession();
		
		if (false){
		//if ( isRevocated(sslSession) ) {
			System.out.println("*****CERTIFICAT REVOCATED");
			certificatOK = false;
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		try {
			System.out.println(sslSession.getPeerPrincipal());
			clientID = String.valueOf(sslSession.getPeerPrincipal().hashCode());
			System.out.println("CLIENT ID : " + clientID);
		} catch (SSLPeerUnverifiedException e) {
			e.printStackTrace();
		}
	}

	public void run() {

		OutputStream outStream =null ;
		PrintWriter outWriter = null;

		InputStream inStream = null;
		BufferedReader inReader = null;

		// Waiting for Client to connect through Socket
		try {
			outStream = clientSocket.getOutputStream();
			outWriter = new PrintWriter(outStream, true);

			// Sending welcome message:
			outWriter.println("WELCOME");  

			inStream  = clientSocket.getInputStream();
			inReader = new BufferedReader(new InputStreamReader(inStream));

		} catch (Exception e) {
			//e.printStackTrace();
		}

		SDFSProtocol sdfsp = new SDFSProtocol();

		while ( true && certificatOK) {    	        	
			//System.out.println("------------	NEW CYCLE	------------");

			try {
				byte[] inBytes = new byte[20000];

				System.out.println("*****Waiting for client message...");
				int numBytesRead = inStream.read(inBytes, 0, inBytes.length);
				//System.out.println("Number of bytes read : " + numBytesRead);

				byte[] usefulInBytes =  new byte[numBytesRead];
				System.arraycopy(inBytes, 0, usefulInBytes, 0, numBytesRead);	
				//System.out.println("LOG SERVER : REQUEST *"+ new String(usefulInBytes)+"*");

				byte[] outBytes = sdfsp.processRequest(usefulInBytes, clientID);

				if (outBytes == null) {
					System.out.println("*****Server thread shuting down...");
					break;
				}  

				//System.out.println("LOG SERVER : RESPONSE " + new String(outBytes) +" | RESPONSE SIZE "+outBytes.length );
				outStream.write(outBytes, 0,  outBytes.length);
				outStream.flush(); 	
			} catch (IOException e) {
				e.printStackTrace();
			}	

		} // fin du while

		try {
			inReader.close();
			inStream.close();

			outWriter.close();
			outStream.close();

			clientSocket.close();
		} catch (Exception e) {
			//e.printStackTrace();
		}

		System.out.println("*****Server thread off.");
	}
	
	
	public static boolean isRevocated(SSLSession sslSession) {
		try {
			javax.security.cert.X509Certificate[] crt = sslSession.getPeerCertificateChain();
			javax.security.cert.X509Certificate x509 =  crt[0];
			BigInteger bigint = x509.getSerialNumber();
			System.out.println("********" + bigint.toString(16));
	
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			String path = "./myCA/cacrl.pem";
			InputStream is = new FileInputStream(path);         
			X509CRL  crl = (X509CRL) cf.generateCRL(is);
	
			// VERIFY CRL 
			RSAPublicKey rsapub = null ;
			InputStream is1 = new FileInputStream("./myCA/cacert.crt");
			CertificateFactory cf1 = CertificateFactory.getInstance("X.509");
			X509Certificate cert = (X509Certificate) cf1.generateCertificate(is1);
			is1.close();
	
			rsapub = (RSAPublicKey) cert.getPublicKey();
			crl.verify(rsapub);    
	
			// get th serial numbers			
			X509CRLEntry crlentry =crl.getRevokedCertificate(bigint);
			if(crlentry == null){
				return false;
			} else {
				BigInteger bigint2 = crlentry.getSerialNumber();
				System.out.println("********" + bigint2.toString(16));
				System.out.println("********" + bigint.equals(bigint2));
				return bigint.equals(bigint2);
			}
		} catch (NullPointerException n){
			System.out.println("NULL EXCEPTION ");
			n.printStackTrace();			
			return false;
		} catch (Exception e) {
			System.out.println("EXCEPTION ");
			e.printStackTrace();
			return false;
		}
	}
}